package com.meshnetics.gb.type;

import java.util.Map;

/**
 * Interface for custom formatters of values. These formatters expected to be customizable and provide information and
 * parameters for interaction with end user (human). Customization is provided in terms of named parameters and their
 * values. Each parameter should have default value (may be null, nulls passed in set method should be treated as
 * setting of default value). Each <code>CustomFormatter</code> should have default constructor creating formatter
 * with all parametres equal to their default values.
 *
 * @author AKovylin
 */
public interface CustomFormatter extends Formatter {
    /**
     * This code represents general meaning of custom format itself. Usage of this code in anyway is not required.
     */
    final int FORMAT_CUSTOM = 0;

    /**
     * Description of formatter.
     *
     * @return description of formatter
     */
    String getFormatterDescription();

    /**
     * Returns array of supported data types. Types extending (in Java terms) these types should not be considered
     * as supproted by this formatter.
     *
     * @return array of supported data types or null if inapplicable
     */
    DataType[] getSupportedTypes();

    /**
     * Returns array of supported data types implementation classes.
     * Types extending (in Java terms) these types should not be considered as supproted by this formatter.
     *
     * @return array of supported data types implementation classes or null if inapplicable
     */
    Class[] getSupportedTypesClasses();

    /**
     * Returns array of codes of supported formats. In general for customized formatter array should contain only one
     * <code>FORMAT_CUSTOM</code> value. For models with centralized storage of possible formats and lots of formatters
     * subset of supported formats should be returned.
     *
     * @return array of codes of supported formats
     */
    int[] getSupportedFormats();

    /**
     * Returns short (one string expected) description of supported format.
     *
     * @param format code of supported format
     * @return short description of supported format
     * @throws IllegalArgumentException thrown if specified format is not supported
     */
    String getFormatShortDescription(int format);

    /**
     * Returns long (multiline in general) description of supported format.
     *
     * @param format code of supported format
     * @return long description of supported format
     * @throws IllegalArgumentException thrown if specified format is not supported
     */
    String getFormatLongDescription(int format);

    /**
     * Returns array of parameters supported by this custom formatter.
     *
     * @return array of parameters supported by this custom formatter.
     */
    String[] getSupportedParameters();

    /**
     * Returns class of value of supported parameter.
     *
     * @param parameter supported parameter
     * @return class of value of supported parameter
     * @throws NullPointerException     thrown if parameter is null
     * @throws IllegalArgumentException thrown if specified parameter is not supported
     */
    Class getParameterType(String parameter);

    /**
     * Returns value of supported parameter. Value should be is Object of class returned by
     * {@link #getParameterType(String)}.
     *
     * @param parameter supported parameter
     * @return value of supported parameter
     * @throws NullPointerException     thrown if parameter is null
     * @throws IllegalArgumentException thrown if specified parameter is not supported
     */
    Object getParameterValue(String parameter);

    /**
     * Sets value of supported parameter. Nulls should be expected and treated as default value.
     * Default value may be null.
     *
     * @param parameter supported parameter
     * @param value     value to be set
     * @throws NullPointerException     thrown if parameter is null
     * @throws IllegalArgumentException thrown if specified parameter is not supported or value is of wrong class or
     *                                  is not withing valid range (valid values maybe specified in description)
     */
    void setParameterValue(String parameter, Object value);

    /**
     * Creates new custom formatter of this class with parameters redefined from provided <code>Dictionary</code>.
     *
     * @param params mapping of parameter->value for parameters that must be redefined
     * @return new custom formatter with parameters containing in dictionary setted to provided values
     * @throws NullPointerException     thrown if params is null
     * @throws IllegalArgumentException thrown if value of any of parameter is not supported or value is of wrong class
     */
    CustomFormatter derive(Map params);
}
